package handle

import (
	"encoding/json"
	"fmt"
	"gitee.com/git_public/vfaith/builtin/shape"
	"github.com/mitchellh/mapstructure"
	"github.com/shopspring/decimal"
	"io"
	"reflect"
)

func Unmarshal(r io.Reader, v any) error {
	body, err1 := io.ReadAll(r)
	if err1 != nil {
		return err1
	}

	var dataMap map[string]interface{} // 或者使用你定义的struct
	if err := json.Unmarshal(body, &dataMap); err != nil {
		return err
	}

	if err := CusDecode(dataMap, v); err != nil {
		return err
	}

	return nil
}

func MapUnmarshal(dataMap *shape.Map, v any) error {
	if err := CusDecode(dataMap.Store(), v); err != nil {
		return err
	}

	return nil
}

func CusDecode(input, output interface{}) error {
	config := &mapstructure.DecoderConfig{
		Metadata:         nil,
		Result:           output,
		WeaklyTypedInput: true,
		TagName:          "json",
		DecodeHook: mapstructure.ComposeDecodeHookFunc(
			cusHookFunc, // 自定义的字符串到 CusTime 转换函数
		),
	}

	decoder, err := mapstructure.NewDecoder(config)
	if err != nil {
		return err
	}

	return decoder.Decode(input)
}

// stringToIntHookFunc 是一个自定义的 DecodeHook，用于将字符串转换为整数
func cusHookFunc(f reflect.Type, t reflect.Type, data interface{}) (interface{}, error) {
	if t.Kind() == reflect.Ptr {
		//if t.Elem().Kind() == reflect.Int {
		//	return strconv.Atoi(data.(string))
		//}
	}
	if f.Kind() == reflect.String && t == reflect.TypeOf(shape.CusTime{}) {
		strTime := data.(string)
		cusTime := shape.NewCusTime(strTime)
		if cusTime == nil {
			return nil, fmt.Errorf("输入参数 '%s' 无法转换为 [shape.CusTime]", strTime)
		}
		return cusTime, nil
	}
	if f.Kind() == reflect.String && t == reflect.TypeOf(shape.UnixTime{}) {
		strTime := data.(string)
		unixTime := shape.NewUnixTime(strTime)
		if unixTime == nil {
			return nil, fmt.Errorf("输入参数 '%s' 无法转换为 [shape.UnixTime]", strTime)
		}
		return unixTime, nil
	}
	if f.Kind() == reflect.String && t == reflect.TypeOf(decimal.Decimal{}) {
		str := data.(string)
		if str == "" {
			return &decimal.Decimal{}, nil
		}
		d, err := decimal.NewFromString(str)
		if err != nil {
			return nil, fmt.Errorf("error decoding string '%s': %s", str, err)
		}
		return d, nil
	}
	// 否则，返回原始值
	return data, nil
}
